<?php

namespace fakis\config;

use fakis\config\adapters\AdapterInterface;
use fakis\config\adapters\FileAdapter;
use yii\base\InvalidConfigException;
use yii\di\Instance;

/**
 * 配置模型
 *
 * @author Fakis <fakis738@qq.com>
 */
class Model extends \fakis\core\base\DynamicModel
{
    /**
     * @var Component
     */
    public $component;

    /**
     * @var AdapterInterface
     */
    public $adapter = ['class' => FileAdapter::class];

    /**
     * @var string
     */
    public $target;

    /**
     * @var string
     */
    public $symbol;

    /**
     * 构造方法
     * @param Component $component
     * @param array $config
     * @throws InvalidConfigException
     */
    public function __construct($component, $config = [])
    {
        $this->component = $component;
        $this->adapter = Instance::ensure($component->adapter);
        $this->target = $component->target;
        $this->symbol = $component->symbol;

        if (!is_a($this->target, ConstantInterface::class, true)) {
            throw new InvalidConfigException('配置项定义有误');
        }

        parent::__construct(forward_static_call([$this->target, 'attributes']), $config);
    }

    /**
     * 保存配置
     * @return bool
     */
    public function store()
    {
        if (!$this->validate()) {
            return false;
        }

        // 对比改变后的属性值，如果没有变动则不需要储存
        $changedAttributes = $this->getChangeAttributes();
        if (!empty($changedAttributes)) {
            $this->adapter->store($this->symbol, $this->attributes);
            $this->resetOldAttributes();
        }

        // 触发保存后事件
        $this->component->trigger(StoreEvent::AFTER_STORE, new StoreEvent([
            'changedAttributes' => $changedAttributes,
        ]));

        return true;
    }

    /**
     * 恢复配置默认值
     * @return bool
     */
    public function restore(array $names = null)
    {
        $attributes = [];
        $names = $names === null ? $this->attributes() : $names;
        foreach ($this->getDefaultAttributes() as $name => $value) {
            if (in_array($name, $names, true)) {
                $attributes[$name] = $value;
            }
        }

        $this->load($attributes);
        $changedAttributes = $this->getChangeAttributes();
        if ($this->store()) {
            // 触发保存后事件
            $this->component->trigger(StoreEvent::AFTER_RESTORE, new StoreEvent([
                'changedAttributes' => $changedAttributes,
            ]));
            return true;
        }
        return false;
    }

    /**
     * 解析模型属性
     */
    protected function parseAttributes()
    {
        parent::parseAttributes();

        $data = $this->adapter->query($this->symbol);
        if (!empty($data)) {
            foreach ($data as $name => $value) {
                if ($this->hasAttribute($name)) {
                    $this->$name = $value;
                }
            }
        }
    }

    /**
     * 返回此模型类应使用的表单名称
     * @return string
     */
    public function formName()
    {
        return 'ConfigForm_' . $this->symbol;
    }
}